package com.woniu.uums.service.impl;

import java.util.Date;

import cn.hutool.crypto.SecureUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.woniu.common.utils.*;
import com.woniu.uums.dto.*;
import com.woniu.uums.mapper.AuthorityMapper;
import com.woniu.uums.mapper.ReqPathMapper;
import com.woniu.uums.mapper.RoleReqPathMapper;
import com.woniu.uums.pojo.*;
import com.woniu.uums.service.*;
import com.woniu.uums.vo.RepPathVO;
import com.woniu.uums.vo.UserVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import static com.woniu.common.constant.FinanceConstant.RequestFilter.USER_REQ_PATH;
import static com.woniu.common.constant.FinanceConstant.RequestFilter.USER_ROLE;
import static com.woniu.common.constant.FinanceConstant.Salt.SALT;

/**
 * packageName com.woniu.uums.service.impl
 *
 * @author zxyang3636
 * @version JDK 8
 * @className AuthorityServiceImpl
 * @date 2024/8/12
 * @description TODO
 */
@Service
public class AuthorityServiceImpl implements AuthorityService {
    @Autowired
    private ZyRoleManageService zyRoleManageService;

    @Autowired
    private AuthorityMapper authorityMapper;

    @Autowired
    private RoleReqPathService roleReqPathService;

    @Autowired
    private RoleReqPathMapper roleReqPathMapper;

    @Autowired
    private RoleService roleService;

    @Autowired
    private MenuService menuService;

    @Autowired
    private MenuRoleService menuRoleService;

    @Autowired
    private ReqPathMapper reqPathMapper;

    @Autowired
    private ReqPathService reqPathService;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private ZyManageService zyManageService;


    @Override
    public ResponseData<?> selRole() {
        List<Role> list = roleService.lambdaQuery().eq(Role::getStatus, 1)
                .list();
        return new ResponseData<>().success(list);
    }


    @Override
    public ResponseData<?> selAllMenu() {
        List<Menu> allMenu = menuService.lambdaQuery()
                .eq(Menu::getStatus, 1)
                .list();

        List<Menu> parentMenus = new ArrayList<>();     // 所有的父菜单集合
        for (Menu menu : allMenu) {
            if (menu.getParentId() == -1) {
                Menu parentMenu = new Menu();
                parentMenu.setId(menu.getId());
                parentMenu.setName(menu.getName());
                parentMenu.setLink(menu.getLink());
                parentMenu.setParentId(menu.getParentId());
                parentMenu.setIcon(menu.getIcon());
                parentMenu.setStatus(menu.getStatus());
                parentMenu.setChildren(null);
                parentMenus.add(parentMenu);
            }
        }

        for (Menu parentMenu : parentMenus) {
            ArrayList<Menu> childrenMenus = new ArrayList<>();
            for (Menu menu : allMenu) {
                if (menu.getParentId().equals(parentMenu.getId()) && menu.getParentId() != -1) {
                    childrenMenus.add(menu);
                }
            }
            parentMenu.setChildren(childrenMenus);
        }

        return new ResponseData<>().success(parentMenus);
    }

    @Override
    public ResponseData<?> selDefaultSelected(String roleId) {
        List<MenuRole> list = menuRoleService.lambdaQuery().eq(MenuRole::getRoleId, roleId).list();
        return new ResponseData<>().success(list);
    }

    @Override
    @Transactional
    public ResponseData<?> updateRoleMenu(MenuRoleUpdateDTO menuRoleUpdateDTO) {
        menuRoleService
                .lambdaUpdate()
                .eq(MenuRole::getRoleId, menuRoleUpdateDTO.getRoleId())
                .remove();
//        menuRoleService.removeById(menuRoleUpdateDTO.getRoleId());

        ArrayList<MenuRole> menuRoles = new ArrayList<>();
        for (String s : menuRoleUpdateDTO.getMenuId()) {
            MenuRole menuRole = new MenuRole();
            menuRole.setId(String.valueOf(UUID.randomUUID()));
            menuRole.setRoleId(menuRoleUpdateDTO.getRoleId());
            menuRole.setMenuId(s);
            menuRoles.add(menuRole);
        }
        menuRoleService.saveBatch(menuRoles);
        return new ResponseData<>().success();
    }


    @Override
    public ResponseData<?> selRepPath() {
        List<RepPathVO> repPathVOList = reqPathMapper.selRepPathVO();
        return new ResponseData<>().success(repPathVOList);
    }

    @Override
    public ResponseData<?> selectReqPathByRoleId(String roleId) {
        List<RoleReqPath> roleReqPathList = roleReqPathService.lambdaQuery()
                .eq(RoleReqPath::getRoleId, roleId)
                .list();
        ArrayList<String> requestPathIdList = new ArrayList<>();
        for (RoleReqPath roleReqPath : roleReqPathList) {
            requestPathIdList.add(roleReqPath.getReqPathId());
        }
        if (requestPathIdList.size() == 0) {
            return new ResponseData<>().fail(ResponseEnum.QUERY_EMPTY);
        }
        //List<RepPathVO> repPathVOList = reqPathMapper.querySelectInfo(requestPathIdList);
        return new ResponseData<>().success(requestPathIdList);
    }

    @Override
    @Transactional
    public ResponseData<?> updateRoleReqPath(ReqPathUpdateDTO reqPathUpdateDTO) {
        // 删除
        roleReqPathService.lambdaUpdate().eq(RoleReqPath::getRoleId, reqPathUpdateDTO.getRoleId()).remove();
        // 添加
        ArrayList<RoleReqPath> roleReqPaths = new ArrayList<>();
        for (String requestPathId : reqPathUpdateDTO.getRequestPathIds()) {
            RoleReqPath roleReqPath = new RoleReqPath();
            roleReqPath.setId(String.valueOf(UUID.randomUUID()));
            roleReqPath.setRoleId(reqPathUpdateDTO.getRoleId());
            roleReqPath.setReqPathId(requestPathId);
            roleReqPaths.add(roleReqPath);
        }
        roleReqPathService.saveBatch(roleReqPaths);

        if (reqPathUpdateDTO.getRequestPathIds().size() > 0) {
            List<ReqPath> reqPathList = reqPathService.lambdaQuery().in(ReqPath::getId, reqPathUpdateDTO.getRequestPathIds()).list();
            redisTemplate.delete(USER_REQ_PATH + reqPathUpdateDTO.getRoleId());

            for (ReqPath reqPath : reqPathList) {
                redisTemplate.opsForHash().put(USER_REQ_PATH + reqPathUpdateDTO.getRoleId(), reqPath.getReqPath(), reqPath);
            }
        } else {
            redisTemplate.delete(USER_REQ_PATH + reqPathUpdateDTO.getRoleId());
        }

        return new ResponseData<>().success();
    }

    @Override
    public ResponseData<?> userCachePreheating() {
        List<ZyManage> zyManageList = zyManageService.lambdaQuery().list();
        for (ZyManage manage : zyManageList) {
            List<ZyRoleManage> roleManageList = zyRoleManageService.lambdaQuery().eq(ZyRoleManage::getManageId, manage.getId()).list();
            for (ZyRoleManage zyRoleManage : roleManageList) {
                redisTemplate.opsForHash().put(USER_ROLE + manage.getId(), zyRoleManage.getRoleId(), manage);
            }
        }
        return new ResponseData<>().success("Manage预热成功");
    }


    @Override
    public ResponseData<?> requestPathCachePreheating() {
        List<ZyManage> zyManageList = zyManageService.lambdaQuery().list();
        for (ZyManage manage : zyManageList) {
            List<ZyRoleManage> roleManageList = zyRoleManageService.lambdaQuery().eq(ZyRoleManage::getManageId, manage.getId()).list();
            for (ZyRoleManage zyRoleManage : roleManageList) {
//            String manageRoleId = manage.getManageRoleId();
                List<RoleReqPath> roleReqPathList = roleReqPathService.lambdaQuery().eq(RoleReqPath::getRoleId, zyRoleManage.getRoleId()).list();
                for (RoleReqPath roleReqPath : roleReqPathList) {
                    if (roleReqPath == null) {
                        break;
                    }
                    List<ReqPath> list = reqPathService.lambdaQuery().eq(ReqPath::getId, roleReqPath.getReqPathId()).list();
                    for (ReqPath reqPath : list) {
                        redisTemplate.opsForHash().put(USER_REQ_PATH + roleReqPath.getRoleId(), reqPath.getReqPath(), reqPath);
                    }
                }
            }
        }
        return new ResponseData<>().success("user_request_path_cache_success");
    }

    @Override
    public ResponseData<?> selUserByCondition(PageParam<UserQueryDTO> pageParam) {
        PageHelper.startPage(pageParam.getPageNum(), pageParam.getPageSize());
        List<UserVO> list = authorityMapper.selUserByCondition(pageParam.getParam());
        PageInfo<UserVO> userVOPageInfo = new PageInfo<>(list);
        return new ResponseData<>().success(userVOPageInfo);
    }

    @Override
    public ResponseData<?> addUser(ManageAddDTO manageAddDTO) throws Exception {
        ZyManage manage = new ZyManage();
        long l = new SnowflakeIdGenerator().nextId();
        manage.setId(String.valueOf(l));
        manage.setManageAccount(manageAddDTO.getAccount());
        manage.setManagePwd("aa20cf9a94f300f544d559ee7010730e");
//        manage.setManageRoleId(manageAddDTO.getRoleId());
        manage.setManageNickName(manageAddDTO.getNickName());
        manage.setManageCreateTime(new Date());
        manage.setManageCreateBy(GetManageUserNickName.getUserName());
        manage.setManageUpdateTime(new Date());
        manage.setManageUpdateBy(GetManageUserNickName.getUserName());
        zyManageService.save(manage);
        return new ResponseData<>().success();
    }

    @Override
    public ResponseData<?> updateManagePwd(ZyManage zyManage) {
        String password = SecureUtil.md5(zyManage.getManagePwd() + SALT);
        zyManageService.lambdaUpdate()
                .eq(ZyManage::getId, zyManage.getId())
                .set(ZyManage::getManagePwd, password)
                .update();
        return new ResponseData<>().success();
    }

    @Override
    public ResponseData<?> deleteUser(String manageId) {
        zyManageService.lambdaUpdate()
                .eq(ZyManage::getId, manageId)
                .remove();
        return new ResponseData<>().success();
    }

    @Override
    public ResponseData<?> selManageRoleByMangeId(String manageId) {
        List<ZyRoleManage> zyRoleManageList = zyRoleManageService.lambdaQuery()
                .eq(ZyRoleManage::getManageId, manageId)
                .list();
        ArrayList<String> roleIdList = new ArrayList<>();
        for (ZyRoleManage zyRoleManage : zyRoleManageList) {
            roleIdList.add(zyRoleManage.getRoleId());
        }
        if (roleIdList.size() == 0) {
            ArrayList<Object> list = new ArrayList<>();
            return new ResponseData<>().fail(ResponseEnum.QUERY_EMPTY, list);
        }
        List<Role> roleList = roleService.lambdaQuery()
                .in(Role::getId, roleIdList)
                .eq(Role::getStatus, 1)
                .list();
        return new ResponseData<>().success(roleList);
    }

    @Override
    public ResponseData<?> addManageRole(ManageUpdateRoleDTO manageUpdateRoleDTO) throws InterruptedException {
        redisTemplate.opsForHash().delete(USER_ROLE + manageUpdateRoleDTO.getManageId(), manageUpdateRoleDTO.getRoleId() + "");

        ZyRoleManage zyRoleManage = new ZyRoleManage();
        zyRoleManage.setId(String.valueOf(new SnowflakeIdGenerator().nextId()));
        zyRoleManage.setManageId(manageUpdateRoleDTO.getManageId());
        zyRoleManage.setRoleId(manageUpdateRoleDTO.getRoleId());
        zyRoleManageService.save(zyRoleManage);

        // 睡
        Thread.sleep(200);
        redisTemplate.opsForHash().delete(USER_ROLE + manageUpdateRoleDTO.getManageId(), manageUpdateRoleDTO.getRoleId() + "");
        redisTemplate.opsForHash().put(USER_ROLE + manageUpdateRoleDTO.getManageId(), manageUpdateRoleDTO.getRoleId(), manageUpdateRoleDTO);
        return new ResponseData<>().success();
    }


    @Override
    public ResponseData<?> deleteManageRole(ManageUpdateRoleDTO manageUpdateRoleDTO) {
        redisTemplate.opsForHash().delete(USER_ROLE + manageUpdateRoleDTO.getManageId(), manageUpdateRoleDTO.getRoleId() + "");
        zyRoleManageService.lambdaUpdate()
                .eq(ZyRoleManage::getManageId, manageUpdateRoleDTO.getManageId())
                .eq(ZyRoleManage::getRoleId, manageUpdateRoleDTO.getRoleId())
                .remove();
        return new ResponseData<>().success();
    }
}
